import Storage from '@/ControlTower/storage.js';
import EventBus from '@/ControlTower/eventBus.js'
// 路由记录 // 定义一个名为 RouterRecord 的对象，该对象是一个 Vue 插件
export default {
	install(Vue, options = {}) {
		// 获取插件配置项中的 key 值，默认为 "router-record"
		const key = options.key || 'router-record';
		const storage_crypto = Storage.install(Vue, options);
		const {
			$storage
		} = storage_crypto;
		/**
		 *  获取 Vue 实例中的 storage 对象  
		 *  定义记录路由历史的类 */
		class Record {
			constructor() {
				// 保存当前路由路径
				this.currentRoute = this.getCurrentRoute();
				// 从本地缓存中获取路由历史记录
				this.recordAry = $storage.get(key) || [];
				this.isReopening = false;
			}
			// 获取当前路由
			getCurrentRoute() {
				const pages = getCurrentPages();
				if (pages.length > 0) {
					const currentPage = pages[pages.length - 1];
					return currentPage.route;
				}
				return '';
			}
			// 更新路由历史记录数组并将其存入本地缓存
			upRecordAry(ary) {
				// 将路由历史记录存入本地缓存
				$storage.set(key, ary);
				// 更新路由历史记录数组
				this.recordAry = ary;
			}

			// 处理跳转路由的方法
			handler(data, callBack) {
				this.currentRoute = this.getCurrentRoute();
				if (!data.success) {
					data.success = () => {}
				}
				const {
					url
				} = data;
				// 如果跳转的路由地址不存在，则抛出错误
				if (url === undefined) {
					throw `url:${url}`;
				} else {
					// 否则执行回调函数
					callBack(url);
					// 恢复重新打开函数
					this.isReopening = false;
				}
			}
			// 导航到新页面或 tabBar 页面，并将新的路由信息添加到路由历史记录中
			navigateToOrSwitchTabWithRecord(data, key) {
				const flag = data.flag; // 不保存当前的路由
				this.handler(data, url => {
					// 如果上一次跳转使用了 lastKey，则直接返回上一页 
					if (flag || this.cleanRoute(this.currentRoute) === this.cleanRoute(this
							.recordAry.slice(-1)[0])) {
						// 将新的路由信息添加到路由历史记录中
						this.upRecordAry(this.recordAry.concat(url));
					} else {
						// 将新的路由信息添加到路由历史记录中
						this.upRecordAry(this.recordAry.concat(this.currentRoute, url));
					}
					uni[key](data);
				});
			}
			/**
			 * 导航到新页面，并将新的路由信息添加到路由历史记录中
			 * @param {Object} options - 跳转参数对象，包含以下属性：
			 *   @param {string} url - 跳转的页面路径
			 *   @param {string} type - 跳转类型，可选值为 'navigateTo'、'switchTab'、'redirectTo'、'reLaunch'
			 *   @param {Object} [query] - 传递给目标页面的参数
			 *   @param {Function} [success] - 跳转成功的回调函数
			 *   @param {Function} [fail] - 跳转失败的回调函数
			 *   @param {Function} [complete] - 跳转完成的回调函数
			 *   @param {string} [animationType] - 页面切换动画类型
			 *   @param {number} [animationDuration] - 页面切换动画的时间
			 */
			navigateTo(data) {
				this.navigateToOrSwitchTabWithRecord(data, 'navigateTo');
			}
			/**
			 * 转到 tabBar 页面，并将新的路由信息添加到路由历史记录中
			 * @param {Object} options - 跳转参数对象，包含以下属性：
			 *   @param {string} url - 跳转的页面路径
			 *   @param {string} type - 跳转类型，可选值为 'navigateTo'、'switchTab'、'redirectTo'、'reLaunch'
			 *   @param {Object} [query] - 传递给目标页面的参数
			 *   @param {Function} [success] - 跳转成功的回调函数
			 *   @param {Function} [fail] - 跳转失败的回调函数
			 *   @param {Function} [complete] - 跳转完成的回调函数
			 *   @param {string} [animationType] - 页面切换动画类型
			 *   @param {number} [animationDuration] - 页面切换动画的时间
			 */
			switchTab(data) {
				let str = 'switchTab';
				const ary = $storage.get(key + str) || [];
				$storage.set(key + str, Array.from(new Set([...ary, data.url])));
				this.navigateToOrSwitchTabWithRecord(data, str);
			}
			/**
			 * 跳转到新页面，会关闭当前页面，并将新的路由信息替换掉当前路由历史记录中最后一个路由信息
			 * @param {Object} options - 跳转参数对象，包含以下属性：
			 *   @param {string} url - 跳转的页面路径
			 *   @param {string} type - 跳转类型，可选值为 'navigateTo'、'switchTab'、'redirectTo'、'reLaunch'
			 *   @param {Object} [query] - 传递给目标页面的参数
			 *   @param {Function} [success] - 跳转成功的回调函数
			 *   @param {Function} [fail] - 跳转失败的回调函数
			 *   @param {Function} [complete] - 跳转完成的回调函数
			 *   @param {string} [animationType] - 页面切换动画类型
			 *   @param {number} [animationDuration] - 页面切换动画的时间
			 */
			redirectTo(data) {
				this.handler(data, url => {
					const {
						success,
						...obj
					} = data;
					// 跳转到新页面
					uni.redirectTo({
						...obj,
						success: (res) => {
							success(res);
							// 更新路由历史记录数组
							this.upRecordAry(this.recordAry.concat(url));
						}
					});

				});
			}
			/**
			 * 关闭所有页面并跳转到应用程序的某个页面
			 * @param {Object} options - 跳转参数对象，包含以下属性：
			 *   @param {string} url - 跳转的页面路径
			 *   @param {string} type - 跳转类型，可选值为 'navigateTo'、'switchTab'、'redirectTo'、'reLaunch'
			 *   @param {Object} [query] - 传递给目标页面的参数
			 *   @param {Function} [success] - 跳转成功的回调函数
			 *   @param {Function} [fail] - 跳转失败的回调函数
			 *   @param {Function} [complete] - 跳转完成的回调函数
			 *   @param {string} [animationType] - 页面切换动画类型
			 *   @param {number} [animationDuration] - 页面切换动画的时间
			 * @param {Array} arr - 新的路由列表
			 */
			// 
			reLaunch(data, ary = []) {
				this.handler(data, url => {
					const {
						success,
						...obj
					} = data;
					// 关闭所有页面并跳转到应用程序的某个页面
					uni.reLaunch({
						...obj,
						success: (res) => {
							// 更新路由历史记录数组
							this.upRecordAry([url, ...ary]);
							success(res);
							// this.reopenPage(ary);
						}
					});
				});
			}

			// 返回到上一个页面或多个页面
			navigateBack(delta = 1) {
				// 如果是在 H5 环境下，则使用浏览器的后退功能返回上一页
				if (process.env.UNI_PLATFORM === 'h5') {
					if (!this.currentRoute) {
						const [url = '/', ...arr] = this.recordAry.slice(0, -1);
						const data = this.recordAry[this.recordAry.length - 1];
						this.reLaunch({
							url: url.startsWith('/') ? url : '/' + url
						}, arr);
					} else {
						window.history.back();
					}

					// 处理h5刷新后不能正常反回问题
					/* const [one, ...args] = this.recordAry.slice(0, -1);
					this.reLaunch({
						url: one
					}, args); */
				} else {
					// 否则使用 uni-app 提供的 navigateBack 方法返回上一页
					uni.navigateBack({
						delta
					});
				}
			}


			// 清除路由历史记录
			clearCurrentRecord() {
				this.upRecordAry(this.recordAry.slice(0, -1));
			}

			/**
			 * 重新打开页面函数，逐个重新打开页面
			 * @param {Array} recordAry 路由历史记录数组
			 * @param {string} currentRoute 当前页面路由路径
			 */
			reopenPage(recordAry, currentRoute) {
				// 获取需要切换 Tab 的页面列表
				const switchTabPages = uni.getStorageSync(key + 'switchTab') || [];
				// 定义递增函数来处理页面打开操作
				const openPage = (index) => {
					if (index >= recordAry.length) {
						return;
					}
					const url = recordAry[index];
					// 如果当前路由路径不在本次循环中，则重新打开页面
					if (!currentRoute || currentRoute !== this.cleanRoute(url)) {
						// 使用延迟执行的方式重新打开页面，以避免在同一个事件循环中导致页面渲染问题
						const navType = switchTabPages.includes(url) ? 'switchTab' :
							'navigateTo';
						// 根据页面是否需要切换 Tab 来选择导航方式
						uni[navType]({
							url,
							complete: () => {
								openPage(index + 1); // 递增调用打开下一个页面
							}
						});
					} else {
						openPage(index + 1); // 直接递增调用打开下一个页面
					}
				}
				openPage(0); // 调用递增函数开始打开页面
			}

			/**
			 * 重新打开之前的页面
			 * @param {string} token 访问令牌
			 * @param {Array} exemptedRoutes 免除认证的页面路由列表
			 */
			reopenPreviousPages(token, exemptedRoutes = [], callBack) {
				// 从本地缓存中获取路由历史记录
				const recordAry = $storage.get(key) || [];
				// 获取当前路由路径和最后一个历史记录路径
				const currentRoute = this.getCurrentRoute();
				const lastRoute = recordAry[recordAry.length - 1] || currentRoute;

				// 清理路由路径中的斜杠
				const cleanedCurrentRoute = this.cleanRoute(currentRoute);
				const cleanedLastRoute = this.cleanRoute(lastRoute);

				// 如果当前路由路径和最后一个历史记录路径相同，则不需要重新打开页面
				if (cleanedCurrentRoute === cleanedLastRoute) {
					return 'Current route is the same as the last route';
				}

				// 检查当前页面是否在免除认证的页面列表中
				const isExemptedRoute = exemptedRoutes.includes(cleanedCurrentRoute);

				// 如果当前页面需要认证且用户未登录，则跳转到登录页面 
				if (!isExemptedRoute && !token) {
					callBack();
					return '请完善没有登录跳转到登录界面还是指定的界面';
				}
				// 如果已经执行过重新打开，则直接返回
				if (this.isReopening) {
					return 'Already reopening previous pages';
				}

				this.isReopening = true;
				// 重新打开页面
				this.reopenPage(recordAry, currentRoute);
			}

			/**
			 * 清理路由路径中的斜杠
			 * @param {string} route 路由路径
			 * @returns {string} 清理后的路由路径
			 */
			cleanRoute(route) {
				if (!route || route === true) return ''
				return (route.startsWith("/") ? route.substring(1) : route).split('?')[0];
			}
		}
		/* 	for (let key in call) {
			  Object.defineProperty(Vue.prototype, key, {
			    get: function () {
			      return call[key];
			    }
			  });
			} */
		// 在 Vue 实例中添加 $record 对象，可以通过 this.$record 访问路由历史记录功能
		return {
			$record: new Record(),
			...storage_crypto,
			$eventBus: EventBus.install(Vue)
		};

	},
};